﻿/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations
 * under the License.
 *
 * The Original Code is tyzoh.jp code.
 *
 * The Initial Developer of the Original Code is Kazutaka Kurihara.
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */
using System;
using System.Collections;
using System.Windows.Forms;

namespace Qurihara.QBasic
{
	/// <summary>
	/// FocusManager の概要の説明です。
	/// </summary>
	public class FocusManager
	{
		//やることはControl.Leave, Control.Enterと同じなので，delegateを定義しなくてよい．
		//public delegate void EnterFromInternalEventHandler(object sender,EventArgs e);
		//public delegate void LeaveToExternalEventHandler(object sender,EventArgs e);
		public event EventHandler EnterFromInternalEventHandler;
		public event EventHandler LeaveToExternalEventHandler;

		public static int Interval = 100;

		protected ArrayList controls;
		protected Control focusedControl;
		protected Control recentControl;
		protected Timer timer;
		public FocusManager()
		{
			controls = new ArrayList();
			timer = new Timer();
			timer.Interval = Interval;
			timer.Tick +=new EventHandler(timer_Tick);
			timer.Enabled = false;
			focusedControl = null;
			recentControl = null;
		}

		~FocusManager()
		{
			Clear();
		}

		public void Clear()
		{
			foreach(Control c in controls)
			{
				c.MouseEnter -= new EventHandler(c_MouseEnter);
				c.MouseLeave -=new EventHandler(c_MouseLeave);
			}
			controls.Clear();
		}
		public void AddControlRecursive(Control c)
		{
			if (!controls.Contains(c))
			{
				controls.Add(c);
				c.MouseEnter += new EventHandler(c_MouseEnter);
				c.MouseLeave +=new EventHandler(c_MouseLeave);
			}
			if (c.Controls.Count > 0) 
			{
				foreach(Control cc in c.Controls)
				{
					AddControlRecursive(cc);
				}
			}
		}
		public void RemoveControlRecursive(Control c)
		{
			if (controls.Contains(c))
			{
				c.MouseEnter -= new EventHandler(c_MouseEnter);
				c.MouseLeave -=new EventHandler(c_MouseLeave);
			}
			if (c.Controls.Count > 0) 
			{
				foreach(Control cc in c.Controls)
				{
					RemoveControlRecursive(cc);
				}
			}
		}

		private void c_MouseEnter(object sender, EventArgs e)
		{
			focusedControl = (Control)sender;
			recentControl = focusedControl;
		}

		private void c_MouseLeave(object sender, EventArgs e)
		{
			timer.Enabled = true;
			timer.Start();
			focusedControl = null;
		}

		private void timer_Tick(object sender, EventArgs e)
		{
			timer.Stop();
			timer.Enabled = false;
			if (focusedControl != null)
			{//内部遷移だった
				if(EnterFromInternalEventHandler != null) EnterFromInternalEventHandler(focusedControl,new EventArgs());
			}
			else
			{
				if(LeaveToExternalEventHandler != null) LeaveToExternalEventHandler(recentControl,new EventArgs());
			}
		}
	}
}
